<template>
  <div class="doodle-view" :style="{width: 'auto'}">

    <!-- 操作按钮群 -->
    <div class="doodle-handle">
      <div class="doodle-btn-cross">
        <el-button class="doodle-btn" :disabled="historyIndex == -1" @click="back">
          <el-icon><ArrowLeftBold /></el-icon>
        </el-button>
        <el-button class="doodle-btn" :disabled="historyIndex >= history.length-1" @click="redo">
          <el-icon><ArrowRightBold /></el-icon>
        </el-button>
      </div>
      <el-button class="doodle-btn" :type="!isClear ? 'primary' : ''" @click="isClear=false">
        <el-icon class="icon"><EditPen /></el-icon>画笔
      </el-button>
      <el-button class="doodle-btn" :type="isClear ? 'primary' : ''" @click="isClear=true">
        <el-icon class="icon"><Pointer /></el-icon>橡皮擦
      </el-button>

      <div class="option-line-width">
        <div class="line-width-wrap" style="height: 22px;">
          <div class="line-width" :style="{width:currentLineWidth+'px', height:currentLineWidth+'px', background: strokeStyle, opacity: markOpacity}"></div>
        </div>
        <input class="range" v-model="currentLineWidth" type="range" min="5" max="22" />
        <div>画笔大小</div>
      </div>
    </div>

    <div class="doodle-view-content" v-loading='loading' :style="{height: height+'px'}">
      <canvas class="doodle-canvas" :class="isClear && 'clear'" ref="doodleCanvas" :width="loading ? 0 : imgWidth" :height="loading ? 0 : imgHeight" :style="{opacity: markOpacity}" />
      <img class="doodle-img" :src="src" :width="loading ? 0 : imgWidth" :height="loading ? 0 : imgHeight" @load="resetZoom" />

      <div class="float-btn" v-if="showEraseBtn" @click="eraseClick">
        <el-icon class="btn-icon loading" v-if="computeing"><Loading /></el-icon>
        <el-icon class="btn-icon" v-else><MagicStick /></el-icon>
        <div>
          <div>涂抹消除</div>
          <div class="min-font">消耗算力</div>
        </div>
      </div>
    </div>

  </div>
</template>

<script>
/** 图片涂抹 */
/* eslint-disable */
import WebRequest from '@/unit/request.js'
export default {
  name: 'Smear',
  props: {
    // 图片url
    src: {
      type: String,
      default: ''
    },
    // 宽度
    width: {
      type: Number,
      default: 500
    },
    // 高度
    height: {
      type: Number,
      default: 300
    },
    // 涂抹类型：1 - 保留，2 - 擦除
    type: {
      type: Number,
      default: 1
    },
    // 画笔颜色
    strokeStyle: {
      type: String,
      default: '#40387C'
    },
    // 画笔粗细
    lineWidth: {
      type: Array,
      default: [10, 18, 22]
    },
    // 遮罩透明度
    markOpacity: {
      type: Number,
      default: 0.6
    },
    // 是否显示擦除按钮
    showEraseBtn: false,
  },
  data () {
    return {
      history: [],          // 历史记录
      historyIndex: -1,     // 历史记录下标
      dragging: false,      // 是否绘制中
      isClear: false,       // 是否为擦除模式
      imgWidth: 500,        // 图像原始宽度，同时作用于画布
      imgHeight: 300,       // 图像原始高度，同时作用于画布
      zoom: 1,              // 缩放比例
      markImageOriginal: null,      // 原始遮罩图：base64
      markImage: null,      // 遮罩图：base64
      currentLineWidth: 10, // 当前笔触大小
      loading: false,       // 图片是否加载中
      computeing: false,    // 计算中

      canvas: null,
      ctx: null,
      canvasPos: null,
      shadowCanvas: null,
      shadowCtx: null,
      shadowHistory: [],
    }
  },
  created() {
    setTimeout(() => {
      this.init()
    }, 500)
  },
  watch: {
    src: {
      handler() {
        this.resetAll()
      },
      immediate: true
    },
  },
  methods: {
    /** 重置 */
    reset() {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      this.shadowCtx.clearRect(0, 0, this.shadowCanvas.width, this.shadowCanvas.height)
      this.save()
    },

    /** 初始化 */
    init() {
      this.canvas = this.$refs['doodleCanvas']
      this.ctx = this.canvas.getContext('2d',{willReadFrequently:true})
      this.canvasPos = this.canvas.getBoundingClientRect()
			this.canvas.onmousedown = e => this.onMousedown(e)
      this.canvas.onmousemove = e => this.onMousemove(e)
      this.canvas.onmouseup = e => this.onMouseup(e)
      this.canvas.onmouseout = e => this.onMouseout(e)
    },
    /** 重置比例 */
    resetZoom(e) {
      this.loading = true
      let img = new Image()
      img.src = this.src
      img.onload = (e2) => {
        let w = e2.currentTarget.width
        let h = e2.currentTarget.height
        // 计算缩放比例(原图/指定尺寸)
        this.shadowCanvas = document.createElement('canvas')
        this.shadowCtx = this.shadowCanvas.getContext('2d',{willReadFrequently:true})
        this.shadowCanvas.width = w
        this.shadowCanvas.height = h
        // 计算纵横比
        let width = this.width
        let height = parseInt(h * (this.width / w))
        if (w >= h) {
          if (height > this.height) {
            width = parseInt(w * (this.height / h))
            height = this.height
          }
          this.zoom = w / width
        } else {
          width = parseInt(w * (this.height / h))
          height = this.height
          if (width > this.width) {
            width = this.width
            height = parseInt(h * (this.width / w))
          }
          this.zoom = h / height
        }
        this.imgWidth = width
        this.imgHeight = height
        this.loading = false
      }
    },
    /** 重置所有设置 */
    resetAll() {
      if (this.ctx) {
        this.isClear = false
        this.historyIndex = -1
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
        this.history = []
        this.shadowCtx.clearRect(0, 0, this.shadowCanvas.width, this.shadowCanvas.height)
        this.shadowHistory = []
        // 重新读取图片和比例
        this.resetZoom()
      }
    },
    /** 变更图片 */
    onChangeImage() {
      this.resetAll()
    },
    /** 鼠标按下 */
    onMousedown(e) {
      try {
        this.dragging = true
        if (!this.isClear) {
          let pos = this.getCursorPosition(e)
          this.ctx.strokeStyle = this.strokeStyle
          this.ctx.lineWidth = this.currentLineWidth
          this.ctx.lineCap = 'round'
          this.ctx.lineJoin = 'round'
          this.ctx.beginPath()
          this.ctx.moveTo(pos.x, pos.y)

          this.shadowCtx.strokeStyle = this.strokeStyle
          this.shadowCtx.lineWidth = this.currentLineWidth*this.zoom
          this.shadowCtx.lineCap = 'round'
          this.shadowCtx.lineJoin = 'round'
          this.shadowCtx.beginPath()
          this.shadowCtx.moveTo(pos.x*this.zoom, pos.y*this.zoom)
        } else {
          this.clear(e)
        }
      } catch (error) {
        // console.error(error)
      }
    },
    /** 鼠标移动 */
    onMousemove(e) {
      if (!this.dragging) {
        return
      }
      if (!this.isClear) {
        let pos = this.getCursorPosition(e)
        this.ctx.lineTo(pos.x, pos.y)
        this.ctx.stroke()

        this.shadowCtx.lineTo(pos.x*this.zoom, pos.y*this.zoom)
        this.shadowCtx.stroke()
      } else {
        this.clear(e)
      }
    },
    /** 放开鼠标 */
    onMouseup(e) {
      this.dragging = false
      this.save()
    },
    /** 移出画布 */
    onMouseout(e) {
      this.dragging = false
    },
    getCursorPosition(e) {
      return { x: e.offsetX, y: e.offsetY }
      // return {
      //   x: e.clientX - this.canvasPos.left,
      //   y: e.clientY - this.canvasPos.top
      // }
    },
    /** 擦除 */
    clear(e) {
      let pos = this.getCursorPosition(e)
      let lineWidth = this.currentLineWidth
      this.ctx.save()
      this.ctx.beginPath()
      this.ctx.arc(pos.x, pos.y, lineWidth/2, 0, Math.PI * 2)
      this.ctx.clip()
      this.ctx.clearRect(pos.x - lineWidth/2, pos.y - lineWidth/2, lineWidth, lineWidth)
      this.ctx.restore()

      this.shadowCtx.save()
      this.shadowCtx.beginPath()
      this.shadowCtx.arc(pos.x*this.zoom, pos.y*this.zoom, (lineWidth*this.zoom)/2, 0, Math.PI * 2)
      this.shadowCtx.clip()
      this.shadowCtx.clearRect(pos.x*this.zoom - (lineWidth*this.zoom)/2, pos.y*this.zoom - (lineWidth*this.zoom)/2, lineWidth*this.zoom, lineWidth*this.zoom)
      this.shadowCtx.restore()
    },

    /** 写入历史记录 */
    save() {
      try {
        this.history.length = this.historyIndex + 1
        let data = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height)
        this.history.push(data)

        this.shadowHistory.length = this.historyIndex + 1
        let data2 = this.shadowCtx.getImageData(0, 0, this.shadowCanvas.width, this.shadowCanvas.height)
        this.shadowHistory.push(data2)

        this.historyIndex += 1
      } catch (error) {
        // console.error(error)
      }
    },
    /** 后退历史记录 */
    back() {
      this.historyIndex -= 1
      if (this.historyIndex < 0) {
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
        this.shadowCtx.clearRect(0, 0, this.shadowCanvas.width, this.shadowCanvas.height)
        this.historyIndex = -1
        return
      }
      let data = this.history[this.historyIndex]
      if (!data) return

      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      this.ctx.putImageData(data, 0, 0)

      let data2 = this.shadowHistory[this.historyIndex]
      this.shadowCtx.clearRect(0, 0, this.shadowCanvas.width, this.shadowCanvas.height)
      this.shadowCtx.putImageData(data2, 0, 0)
    },
    /** 重做历史记录 */
    redo() {
      this.historyIndex += 1
      if (this.historyIndex >= this.history.length) {
        this.historyIndex = this.history.length - 1
        return
      }
      let data = this.history[this.historyIndex]
      if (!data) return

      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      this.ctx.putImageData(data, 0, 0)

      let data2 = this.shadowHistory[this.historyIndex]
      this.shadowCtx.clearRect(0, 0, this.shadowCanvas.width, this.shadowCanvas.height)
      this.shadowCtx.putImageData(data2, 0, 0)
    },
    /** 输出遮罩 */
    mark(fn) {
      let w = this.shadowCanvas.width
      let h = this.shadowCanvas.height
      let imgData = this.shadowCtx.getImageData(0, 0, w, h)
      let data = imgData.data
      for (let i2 = 0; i2 < data.length; i2 += 4) {
        if (data[i2 + 3] > 0) {
          data[i2 + 0] = data[i2 + 1] = data[i2 + 2] = 255
        }
      }
      let canvas = document.createElement('canvas'),
          canvas2 = document.createElement('canvas'),
          img = new Image()
      canvas2.width = canvas.width = w
      canvas2.height = canvas.height = h
      let ctx = canvas.getContext('2d',{willReadFrequently:true}),
          ctx2 = canvas2.getContext('2d',{willReadFrequently:true})
      ctx.putImageData(imgData, 0, 0)
      img.src = canvas.toDataURL()
      img.onload = () => {
        ctx2.fillStyle = '#000000'
        ctx2.fillRect(0, 0, w, h)
        ctx2.drawImage(img, 0, 0)
        this.markImageOriginal = this.shadowCanvas.toDataURL()
        this.markImage = canvas2.toDataURL()
        canvas.remove()
        canvas2.remove()
        img.remove()
        fn && fn()
      }
    },

    /** 反相 */
    inverting(src, fn = ()=>{}) {
      let canvas = document.createElement('canvas'),
          img = new Image()

      canvas.width = this.shadowCanvas.width
      canvas.height = this.shadowCanvas.height
      img.crossOrigin = '*';
      img.crossOrigin = "Anonymous";
      img.src = src
      img.onload = () => {
        let ctx = canvas.getContext('2d',{willReadFrequently:true})
        ctx.drawImage(img, 0, 0)
        let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
        let data = imgData.data
        for (let i2 = 0; i2 < data.length; i2 += 4) {
          data[i2 + 0] = 255 - data[i2 + 0]
          data[i2 + 1] = 255 - data[i2 + 1]
          data[i2 + 2] = 255 - data[i2 + 2]
          data[i2 + 3] = 255
        }
        ctx.putImageData(imgData, 0, 0)
        let newMarkImage = canvas.toDataURL()
        canvas.remove()
        img.remove()

        fn && fn(newMarkImage)
      }
    },

    /** 输出遮罩 */
    output() {
      this.mark(() => {
        this.$emit('comfirm', {original: this.markImageOriginal, mark: this.markImage})
      })
    },

    /** 选择笔触 */
    selectLineWidth(e) {
      let width = e.currentTarget.dataset.width
      this.currentLineWidth = width
    },

    /** 点击按钮消除按钮 */
    eraseClick() {
      // this.$emit('eraseClick', true)
      if (this.computeing) return

      this.computeing = true
      this.mark(() => {
        // 上传base64图片到oss换取oss地址
        WebRequest.UploadImageDataToOss({
          picBase64: this.markImage,
          callback: async (imgRes) => {
            let markImage = imgRes.data.data
            console.log(this.markImage)
            return 
            try {
              let data = await WebRequest.ComfyUi.UploadImage({ imageUrl: this.src })
              let maskData = await WebRequest.ComfyUi.UploadImage({ imageUrl: markImage })
              if (data.status == 200 && maskData.status == 200) {
                let name = data.data.name
                let maskName = maskData.data.name
                let jobData = await WebRequest.ALi.InteractiveScribbleSegmentation({
                  imageUrl: name,
                  maskImageUrl: maskName,
                  // returnForm: 'rgb_alpha'
                })
                if (jobData.status == 200) {
                  let url = jobData.data.ResultUrl
                  // 反相遮罩
                  this.inverting(url, (invertMark) => {
                    console.log(invertMark)
                  })
                  this.computeing = false
                } else {
                  this.computeing = false
                  this.$message({ type: 'error', message: '获取任务错误' })
                }
              } else {
                this.computeing = false
                console.log('图片上传失败')
              }
            } catch (error) {
              this.computeing = false
              console.log(error)
            }


          },
          error: (e) => {
            console.log('model swap call error:',e)
            this.computeing = false
          }
        })


      })
    },
  }
}
</script>
<style src="./index.scss" lang="scss"></style>
